﻿using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Globalization;
using System.Net;
using System.Net.Sockets;
using ALPackage;
using JetBrains.Annotations;
using UnityEngine;
using Unity.Mathematics;
using UnityEngine.SceneManagement;

namespace HYOK
{

    public static partial class GCommon
    {
        //打印协议发送
        public static void NetSend(string _msg)
        {
            string color = "green";
            string str = string.Format("[{0}] <color={1}>SEND</color> : {2}", Time.frameCount, color, _msg);
            Debug.LogWarning(str);
        }

        //打印协议接受
        public static void NetRecv(string _msg)
        {
            string color = "yellow";
            string str = string.Format("[{0}] <color={1}>RECV</color> : {2}", Time.frameCount, color, _msg);
            Debug.LogWarning(str);
        }

        /// </summary>
        /// 读取对象里面
        /// <returns></returns>
        public static string GetInfoPropertys(object objInfo, StringBuilder strB = null)
        {

            try
            {
                if (null == strB)
                {
                    strB = new StringBuilder();
                }

                if (objInfo == null)
                    return strB.ToString();

                Type tInfo = objInfo.GetType();

                if (objInfo is ICollection)
                {
                    ICollection Ilist = objInfo as ICollection;
                    strB.AppendFormat("size:{0}", Ilist.Count);
                    foreach (object obj in Ilist)
                    {
                        GetInfoPropertys(obj, strB);
                    }
                    return strB.ToString();
                }

                strB.AppendFormat("[");

                if (tInfo.IsValueType || (objInfo is string))
                {
                    strB.AppendFormat(objInfo.ToString() + "]");
                    return strB.ToString();
                }

                MethodInfo[] pInfos = tInfo.GetMethods();
                for (int i = 0, max = pInfos.Length; i < max; i++)
                {
                    MethodInfo pTemp = pInfos[i];
                    string Pname = pTemp.Name;
                    if (!Pname.StartsWith("get") || Pname.EndsWith("MainOrder") || Pname.EndsWith("SubOrder"))
                    {
                        continue;
                    }
                    string pTypeName = pTemp.ReturnType.Name;
                    object Pvalue = pTemp.Invoke(objInfo, null);
                    if (pTemp.ReturnType.IsValueType || pTemp.ReturnType.Name.StartsWith("String"))
                    {
                        string value = (Pvalue == null ? "NULL" : Pvalue.ToString());
                        //strB.AppendFormat("属性名：{0}，属性类型：{1}，属性值：{2}<br/>", Pname, pTypeName, value);
                        strB.AppendFormat("{0}: {1}, ", Pname.Substring(3, Pname.Length - 3), value);
                    }
                    else
                    {
                        //string value = Pvalue == null ? "NULL" : Pvalue.ToString();
                        strB.AppendFormat("({0}){1}:[", pTypeName, Pname.Substring(3, Pname.Length - 3));
                        GetInfoPropertys(Pvalue, strB);
                        strB.Append("]");
                    }
                }
                strB.AppendLine("],");
                return strB.ToString();
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message);
                return "";
            }
        }

        /// <summary>
        /// Add a new child game object.
        /// </summary>
        static public GameObject AddChild(GameObject parent) { return AddChild(parent, true); }

        /// <summary>
        /// Add a new child game object.
        /// </summary>
        static public GameObject AddChild(GameObject parent, bool undo)
        {
            GameObject go = new GameObject();
#if UNITY_EDITOR
            if (undo)
                UnityEditor.Undo.RegisterCreatedObjectUndo(go, "Create Object");
#endif
            if (parent != null)
            {
                Transform t = go.transform;
                t.SetParent(parent.transform);
                t.localPosition = Vector3.zero;
                t.localRotation = Quaternion.identity;
                t.localScale = Vector3.one;
                go.layer = parent.layer;
            }
            return go;
        }

        /***************
         * 追加尺寸文字
         **/
        public static void appendFileSize(long _size, StringBuilder _builder)
        {
            if (null == _builder)
                return;

            //if (_size > 1048576)
            //    _builder.Append((_size / 1048576d).ToString("f2")).Append("Mb ");
            //else if (_size > 1024)
            //    _builder.Append((_size / 1024d).ToString("f2")).Append("Kb ");
            //else
            //    _builder.Append(_size).Append("Byte ");
            if(_size > 12000)
                _builder.Append((_size / 1048576d).ToString("f2")).Append("Mb ");
            else
                _builder.Append("0.01Mb ");
        }

        public static T AddMissingComponent<T>(this GameObject _go) where T : Component
        {
            T comp = _go.GetComponent<T>();
            if (comp == null)
            {
                comp = _go.AddComponent<T>();
            }
            return comp;
        }

        public static T AddMissingComponent<T>(this Component _comp) where T : Component
        {
            GameObject go = _comp.gameObject;
            T comp = go.GetComponent<T>();
            if (comp == null)
            {
                comp = go.AddComponent<T>();
            }
            return comp;
        }

        /********************
         * 使用带入的比较函数，对队列进行排序
         * -1 表示小于，0表示等于， 1表示大于
         * 按照从小到大进行排序
         **/
        public static void sortAscList<T>(List<T> _list, Comparison<T> _judgeFunc)
        {
            if (null == _list || null == _judgeFunc)
                return;

            T minObj = default(T);
            int tempJudgeIdx = 0;
            for (int i = 0; i < _list.Count; i++)
            {
                //假定最小值为第一个
                minObj = _list[i];
                tempJudgeIdx = i;

                //逐个比较
                for (int j = i + 1; j < _list.Count; j++)
                {
                    if (_judgeFunc(minObj, _list[j]) > 0)
                    {
                        minObj = _list[j];
                        tempJudgeIdx = j;
                    }
                }

                //设置当前位置的值
                if (i != tempJudgeIdx)
                {
                    minObj = _list[i];
                    _list[i] = _list[tempJudgeIdx];
                    _list[tempJudgeIdx] = minObj;
                }
            }
        }
        //只取出指定次数的对象
        public static void sortAscList<T>(List<T> _list, Comparison<T> _judgeFunc, int _limitTimes)
        {
            if (null == _list || null == _judgeFunc)
                return;

            T minObj = default(T);
            int tempJudgeIdx = 0;
            for (int i = 0; i < _list.Count; i++)
            {
                //判断是否达到次数
                if (i >= _limitTimes)
                    return;

                //假定最小值为第一个
                minObj = _list[i];
                tempJudgeIdx = i;

                //逐个比较
                for (int j = i + 1; j < _list.Count; j++)
                {
                    if (_judgeFunc(minObj, _list[j]) > 0)
                    {
                        minObj = _list[j];
                        tempJudgeIdx = j;
                    }
                }

                //设置当前位置的值
                if (i != tempJudgeIdx)
                {
                    minObj = _list[i];
                    _list[i] = _list[tempJudgeIdx];
                    _list[tempJudgeIdx] = minObj;
                }
            }
        }
    
        //判断是否为纯数字的字符串
        public static bool IsNum(string _str)
        {
            bool blResult = true;//默认状态下是数字 
            if (_str == "")
                blResult = false;
            else
            {
                for (int i = 0; i < _str.Length; ++i)
                {
                    if (!char.IsNumber(_str[i]))
                    {
                        blResult = false;
                        break;
                    }
                }

                if (blResult)
                {
                    if (int.Parse(_str) == 0)
                        blResult = false;
                }
            }
            return blResult;
        }

        public static bool IsNum(string _str, out int _value)
        {
            bool blResult = true;//默认状态下是数字 
            _value = -1;
            if (_str == "")
                blResult = false;
            else
            {
                for (int i = 0; i < _str.Length; ++i)
                {
                    if (!char.IsNumber(_str[i]))
                    {
                        blResult = false;
                        break;
                    }
                }

                int.TryParse(_str, out _value);
                if (_value < 0)
                    blResult = false;

            }
            return blResult;
        }

        //判断字符串是否只由数字或者字母组成
        public static bool IsNumOrLetter(string str)
        {
            bool result = false;
            for (int i = 0; i < str.Length; i++)
            {
                if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9'))
                {
                    result = true;
                }
                else
                {
                    result = false;
                    break;
                }
            }
            return result;
        }

        //是否按下alt
        public static bool isAltPressed()
        {
            return (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt));
        }

        //将 #00FFF4FF 转换成 Color ，或者将一个 color 转换成 #00FFF4FF 格式
        /// <summary>
        /// color 转换 string
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static string colorToString(Color color)
        {
            int r = Mathf.RoundToInt(color.r * 255.0f);
            int g = Mathf.RoundToInt(color.g * 255.0f);
            int b = Mathf.RoundToInt(color.b * 255.0f);
            int a = Mathf.RoundToInt(color.a * 255.0f);
            string hex = string.Format("{0:X2}{1:X2}{2:X2}{3:X2}", r, g, b, a);
            return hex;
        }

        /// <summary>
        /// string 转换到color, e g :"00FFF4FF"
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static Color stringToColor(string hex)
        {
            byte br = byte.Parse(hex.Substring(0, 2), NumberStyles.HexNumber);
            byte bg = byte.Parse(hex.Substring(2, 2), NumberStyles.HexNumber);
            byte bb = byte.Parse(hex.Substring(4, 2), NumberStyles.HexNumber);
            byte cc = byte.Parse(hex.Substring(6, 2), NumberStyles.HexNumber);
            float r = br / 255f;
            float g = bg / 255f;
            float b = bb / 255f;
            float a = cc / 255f;
            return new Color(r, g, b, a);
        }

        /// <summary>
        /// 帮RichText加上颜色。
        /// </summary>
        public static string addColorForRichText(string txt, Color color)
        {
            string richTextColor = "#" + colorToString(color);
            return string.Format("<color={0}>{1}</color>", richTextColor, txt);
        }

        //是否对应礼拜几
        public static bool IsDayOfWeek(DayOfWeek _day, int _dayOfWeekValue)
        {
            return (_dayOfWeekValue & (1 << (int)_day)) != 0;
        }

        /** 在平面上对象的距离 */
        public static float SqrPlaneDistance(Vector3 _v1, Vector3 _v2)
        {
            return (_v1.x - _v2.x) * (_v1.x - _v2.x) + (_v1.z - _v2.z) * (_v1.z - _v2.z);
        }
        
     
        /// <summary>
        /// 编辑器下修改创建出来的item预制体名称
        /// </summary>
        /// <param name="_go"></param>
        /// <param name="_tag"></param>
        public static void setItemGameObjectName_EditorOnly(GameObject _go, string _tag)
        {
            if (_go == null)
                return;

#if UNITY_EDITOR
            int targetIndex = _go.name.IndexOf("(Clone");
            if (targetIndex < 0)
                return;

            string objName = _go.name.Substring(0, targetIndex);
            _go.name = $"{objName}(Clone_{_tag})";
#endif
        }



        /// <summary>
        /// 获取合并相同item列表
        /// </summary>
        /// <param name="_commonCostItems"></param>
        /// <returns></returns>
        public static List<NPCommonCostItem> getCombineItemList(List<NPCommonCostItem> _commonCostItems)
        {
            if (_commonCostItems == null)
                return null;

            Dictionary<NPCommonItem, NPCommonCostItem> rewardDic = new Dictionary<NPCommonItem, NPCommonCostItem>();

            for (int i = 0; i < _commonCostItems.Count; i++)
            {
                if (_commonCostItems[i] != null && _commonCostItems[i].item != null)
                {
                    if (rewardDic.TryGetValue(_commonCostItems[i].item, out NPCommonCostItem commonCostItem))
                    {
                        if (commonCostItem != null)
                            commonCostItem.count += _commonCostItems[i].count;
                    }
                    else
                    {
                        rewardDic[_commonCostItems[i].item] = new NPCommonCostItem(_commonCostItems[i].item, _commonCostItems[i].count);
                    }
                }
            }

            return new List<NPCommonCostItem>(rewardDic.Values);
        }

   
        

        /// <summary>
        /// 判断这个国家地区是否欧盟
        /// </summary>
        /// <param name="_country"></param>
        /// <returns></returns>
        public static bool getIsEuropeanUnion(string _country)
        {
            //欧盟国家代码
            string[] European_Unions =
            {
                "CY", "FR", "LT", "PL", "PT", "RO", "FI", "EE", "LV", "IE", "DE", "IT", "AT", "HU", "CZ", "CS"
                ,"SI", "GR", "HR", "BG", "MT", "NL", "BE", "LU", "DK", "SE", "ES"
            };
            if (Array.IndexOf(European_Unions, _country) != -1)
                return true;

            return false;
        }

      

        public static T randomListItem<T>(List<T> _list)
        {
            if (_list.Count == 0)
                return default;
            System.Random rn = new System.Random();
            int idx = rn.Next(0, _list.Count - 1);
            return _list[idx];
        }

     
        

        
        /// <summary>
        /// 根据玩家CID获取所在的逻辑服务器ID
        /// </summary>
        /// <returns></returns>
        public static int getServerIdByCId(long _cId)
        {
            return (int)(_cId % 10000);
        }
        
        /// <summary>
        /// 根据玩家CID获取所在的逻辑服务器名称
        /// </summary>
        /// <returns></returns>
        public static string getServerNameByCId(long _cId)
        {
            //TODO 临时处理先，后面名字有包装的话找后台获取一份字典维护
            return $"S-{getServerIdByCId(_cId)}";
        }
    }
}

